#include "FileReader.h"



using namespace FileReader;



/**
 * @brief DocxFileReader构造函数
 * @param filePath DOCX文件路径，必须是有效的文件系统路径
 */
DocxFileReader::DocxFileReader(const std::string& filePath) : m_filePath(filePath)
{}


/**
 * @brief DocxFileReader析构函数
 * @note 释放duckx文档资源并关闭文件
 */
DocxFileReader::~DocxFileReader(){

}


/**
 * @brief 打开DOCX文件并初始化读取器
 * @return 成功打开返回true；文件不存在或格式错误返回false
 * @note 使用duckx库解析DOCX文件结构，支持OOXML格式
 */
bool DocxFileReader::openFile()
{
    bool res = false;

    try {
        // Open the file using duckx library
        m_docx.file(m_filePath);
        m_docx.open();
        res = m_docx.is_open();
        m_paragraph = m_docx.paragraphs();
        if (!res) {
            std::cerr << "Failed to open the docx file: " << m_filePath << std::endl;
        }
        
    }
    catch (const std::exception& e) {
        std::cerr << "Exception occurred while opening the docx file: " << e.what() << std::endl;
        return res;
    }
    return res;
}




std::string DocxFileReader::getContentByString(const std::string& inputString){
    // This method is not implemented in this snippet.
    // It should return the context by string.
    // For now, we return an empty string.
    std::string res = "";
    std::string pattern_str = std::format(R"(\[{}\][\s\S]*\[BeginBook{}\]\s*([\s\S]*)\[EndBook{}\])", inputString, inputString, inputString);
    std::regex pattern(pattern_str);

    std::string content = getNextRequirement();

    if (content.find(inputString) != std::string::npos) {
        std::cout << "Input string found in content." << std::endl;
        std::smatch match;
        if (regex_search(content, match, pattern)) {
            if (match.size() >= 2) {
                res = match[1].str(); // Return the content between BeginBook and EndBook
            }
        }
    }

    return res;
}



std::unordered_map<std::string, std::unordered_map<std::string, std::string>> DocxFileReader::getAllRequirements(){
    // This method reads all requirements from the DOCX file and returns them as a map.
    // Each requirement is stored as a key-value pair in the map, where the key is the main requirement string
    // and the value is another map containing additional context information.
    return m_requirements;
}


std::unordered_map<std::string, std::vector<std::string>> DocxFileReader::getRetroRelationship(){
    // This method reads retro relationships from the DOCX file and returns them as a map.
    // Each retro relationship is stored as a key-value pair in the map, where the key is the main requirement string
    // and the value is a vector of related strings.
    return m_retroRelationship;
}


template <typename T>
void DocxFileReader::concatenateMaps(std::unordered_map<std::string, T>& map1, const std::unordered_map<std::string, T>& map2){
    // This method concatenates two maps of the same type.
    for (const auto& pair: map2) {
        map1[pair.first] = pair.second; // Insert the key-value pairs from map2 into map1
    }
}

template void DocxFileReader::concatenateMaps<std::unordered_map<std::string, std::string>>(std::unordered_map<std::string, std::unordered_map<std::string, std::string>>& map1, const std::unordered_map<std::string, std::unordered_map<std::string, std::string>>& map2);
template void DocxFileReader::concatenateMaps<std::vector<std::string>>(std::unordered_map<std::string, std::vector<std::string>>& map1, const std::unordered_map<std::string, std::vector<std::string>>& map2);

